package cn.wolfcode.business.service.impl;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

import cn.wolfcode.business.domain.BusAppointment;
import cn.wolfcode.business.domain.BusStatement;
import cn.wolfcode.business.service.IBusAppointmentService;
import cn.wolfcode.business.service.IBusStatementService;
import cn.wolfcode.business.vo.BusStatementItemVO;
import cn.wolfcode.common.utils.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import cn.wolfcode.business.mapper.BusStatementItemMapper;
import cn.wolfcode.business.domain.BusStatementItem;
import cn.wolfcode.business.service.IBusStatementItemService;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

/**
 * 结算单明细Service业务层处理
 * 
 * @author wolfcode
 * @date 2025-04-07
 */
@Service
public class BusStatementItemServiceImpl implements IBusStatementItemService 
{
    @Autowired
    private BusStatementItemMapper busStatementItemMapper;

    @Autowired
    private IBusStatementService busStatementService;

    @Autowired
    private IBusAppointmentService appointmentService;


    /**
     * 查询结算单明细
     * 
     * @param id 结算单明细主键
     * @return 结算单明细
     */
    @Override
    public BusStatementItem selectBusStatementItemById(Long id)
    {
        return busStatementItemMapper.selectBusStatementItemById(id);
    }

    /**
     * 查询结算单明细列表
     * 
     * @param busStatementItem 结算单明细
     * @return 结算单明细
     */
    @Override
    public List<BusStatementItem> selectBusStatementItemList(BusStatementItem busStatementItem)
    {
        return busStatementItemMapper.selectBusStatementItemList(busStatementItem);
    }

    /**
     * 新增结算单明细
     * 
     * @param busStatementItem 结算单明细
     * @return 结果
     */
    @Override
    public int insertBusStatementItem(BusStatementItem busStatementItem)
    {
        return busStatementItemMapper.insertBusStatementItem(busStatementItem);
    }

    /**
     * 修改结算单明细
     * 
     * @param busStatementItem 结算单明细
     * @return 结果
     */
    @Override
    public int updateBusStatementItem(BusStatementItem busStatementItem)
    {
        return busStatementItemMapper.updateBusStatementItem(busStatementItem);
    }

    /**
     * 批量删除结算单明细
     * 
     * @param ids 需要删除的结算单明细主键
     * @return 结果
     */
    @Override
    public int deleteBusStatementItemByIds(Long[] ids)
    {
        return busStatementItemMapper.deleteBusStatementItemByIds(ids);
    }

    /**
     * 删除结算单明细信息
     * 
     * @param id 结算单明细主键
     * @return 结果
     */
    @Override
    @Transactional
    public int deleteBusStatementItemById(Long id)
    {
        return busStatementItemMapper.deleteBusStatementItemById(id);
    }

    /*明细项保存功能*/
    @Override
    @Transactional //更新bus_statement(结算单)和插入bus_statement_item(结算单明细项)必须同时成功或失败
    public int itemSave(BusStatementItemVO vo) {
        /*1.验证参数合法性*/
        //对象不能为空
        if(vo == null){
            throw new RuntimeException("非法参数");
        }
        //折扣价格不能为空 明细项集合不能为空
        if(vo.getDiscountAmount() == null || vo.getStatementItems() == null){
            throw new RuntimeException("非法参数");
        }
        //明细项长度不能小于0
        if(vo.getStatementItems().size() <= 0){
            throw new RuntimeException("保存时至少添加一条数据");
        }

        /*2.在结算单明细集合中，随便取一条数据，获取到其中的结算单id，因为传递进来的结算单明细都属于同一个结算单*/
        //获取结算单id
        Long statementId = vo.getStatementItems().get(0).getStatementId();

        /*3.通过结算单id获取结算单对象*/
        BusStatement busStatement = busStatementService.selectBusStatementById(statementId);

        /*4.判断结算单状态，必须为消费中才可以进行保存*/
        //结算单对象不能为空
        if(busStatement == null){
            throw new RuntimeException("非法参数");
        }
        //已支付的结算单不能进行支付
        if(BusStatement.STATUS_PAID.equals(busStatement.getStatus())){
            throw new RuntimeException("已支付的结算单不能进行支付");
        }

        //定义总价格
        BigDecimal totalAmount = new BigDecimal("0");
        //定义总数量
        BigDecimal totalQuantity = new BigDecimal("0");
        //定义折扣价
        BigDecimal discountAmount = vo.getDiscountAmount();
        //先删后加
        busStatementItemMapper.deleteRelationBatchItemByStatementId(statementId);

        /*5.遍历结算单，存入数据库*/
        for (BusStatementItem statementItem : vo.getStatementItems()) {
            busStatementItemMapper.insertBusStatementItem(statementItem);

            /*6.计算总价格和总数量*/
            //计算总价格
            totalAmount = totalAmount.add(statementItem.getItemPrice().multiply(new BigDecimal(statementItem.getItemQuantity())));
            //计算总数量
            totalQuantity = totalQuantity.add(new BigDecimal(statementItem.getItemQuantity()));
        }

        /*7.金额合理性验证*/
        //总金额和折扣金额必须大于0
        if(!(totalAmount.compareTo(new BigDecimal("0")) >= 0 && discountAmount.compareTo(new BigDecimal("0")) >= 0)){
            throw new RuntimeException("非法参数");
        }
        //折扣金额应小于等于总金额
        if(discountAmount.compareTo(totalAmount) > 0){
            throw new RuntimeException("折扣金额应小于等于总金额");
        }

        /*8.更新结算单，一定不能使用全更新方法，防止恶意篡改*/
        return busStatementService.updateAmount(statementId,totalAmount,totalQuantity,discountAmount);
    }

    /*支付功能*/
    @Override
    @Transactional
    public int pay(Long statementId) {
        //判空
        if(statementId == null){
            throw new RuntimeException("非法参数");
        }

        /*1.判断结算单状态，必须处于消费中才可以支付*/
        //根据结算单id获取结算单对象
        BusStatement busStatement = busStatementService.selectBusStatementById(statementId);
        //判空
        if(busStatement == null) {
            throw new RuntimeException("非法参数");
        }
        //必须处于消费中才可以支付
        if(BusStatement.STATUS_PAID.equals(busStatement.getStatus())){
            throw new RuntimeException("该结算单已支付");
        }

        /*2.若是预约用户则需要将预约状态也修改为已支付（前提是结算单关联了预约单）*/
        //若bus_statement表中没有appointment_id 说明不是预约用户
        if(busStatement.getAppointmentId() != null){
            //是预约用户，将预约单的状态修改为已支付
            appointmentService.updateStatusByAppointmentId(busStatement.getAppointmentId(), BusAppointment.STATUS_PAID);
        }

        /*3.结算单需要填写收款人和收款时间、还需要将结算单的状态修改为已支付*/
        //获取登录用户
        Long payId = SecurityUtils.getUserId();
        return busStatementService.updatePayStatusByStatementId(statementId,payId,new Date(),BusStatement.STATUS_PAID);
    }

}
